﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntityComponentSystem.Framework;
using EntityComponentSystem.Demos.SpaceAttack.Components;
using EntityComponentSystem.Framework.Math;

namespace EntityComponentSystem.Demos.SpaceAttack.Systems
{
    public class RenderMapper : ComponentMapper
    {
        public PositionComponent Position { get; private set; }
        public RenderComponent Render { get; private set; }

        protected override void OnInit()
        {
            Position = Entity.GetComponent<PositionComponent>();
            Render = Entity.GetComponent<RenderComponent>();
        }
    }

    public interface IRenderSystem : ISystemProcessor
    {

    }


    public class ConsoleRenderSystem : System<RenderMapper>, IRenderSystem
    {
        private struct ConsoleBlock
        {
            public string Texture;
            public ConsoleColor Color;
        }

        private Dictionary<string, string> textures = new Dictionary<string, string>();
        private ConsoleBlock[,] backBuffer = new ConsoleBlock[80, 60];
        private ConsoleBlock[,] frontBuffer = new ConsoleBlock[80, 60];

        public ConsoleRenderSystem(GameEngine ge)
            : base(ge)
        {
            textures.Add("empty", " ");
            textures.Add("block", "#");
            Console.CursorVisible = false;
        }

        protected override void OnUpdate(long timeDelta, float timeDeltaF)
        {
            for (var i = 0; i < 2; i++ )
            {
                Console.SetCursorPosition(0, i);
                Console.Write("      ");
            }
            Console.SetCursorPosition(0, 0);

            for (var x = 0; x < 80; x++)
                for (var y = 0; y < 60; y++)
                    backBuffer[x, y] = new ConsoleBlock() { Texture = " ", Color = ConsoleColor.White };

            foreach (var am in AllComponentMaps)
            {
                if (!string.IsNullOrEmpty(am.Render.Texture) && textures.ContainsKey(am.Render.Texture))
                {
                    var texture = textures[am.Render.Texture];
                    var pos = am.Position.Value;
                    backBuffer[(int)pos.x, (int)pos.y].Texture = texture;
                    backBuffer[(int)pos.x, (int)pos.y].Color = am.Render.Color;
                }
            }

            for (var y = 0; y < 60; y++)
            {
                for (var x = 0; x < 80; x++)
                {
                    if (backBuffer[x, y].Texture != frontBuffer[x, y].Texture)
                    {
                        Console.SetCursorPosition(x, y);
                        Console.ForegroundColor = backBuffer[x, y].Color;
                        Console.Write(backBuffer[x, y].Texture);

                        frontBuffer[x, y].Texture = backBuffer[x, y].Texture;
                        frontBuffer[x, y].Color = backBuffer[x, y].Color;
                    }
                }
            }
        }

    }
}
